package com.techblor.library.wechat.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;

import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 数据转换工具类
 */
public class DataConvertUtil {

    /**
     * 初始容量
     */
    private static final int INITIAL_CAPACITY = 16;

    /**
     * 对象转 map
     * 指定要转换对象的泛型
     *
     * @param o
     * @param typeReference
     * @param <O>
     * @param <K>
     * @param <V>
     * @return
     */
    public static <O, K, V> Map<K, V> objectToMap(O o, TypeReference<Map<K, V>> typeReference) {
        return JSON.parseObject(JSON.toJSONString(o), typeReference);
    }

    public static <O> Map<String, Object> objectToMap(O o) {
        return JSON.parseObject(JSON.toJSONString(o), new TypeReference<Map<String, Object>>() {
        });
    }

    /**
     * map 转对象
     * 不知道要转换对象的泛型
     *
     * @param map
     * @param typeReference
     * @param <O>
     * @param <K>
     * @param <V>
     * @return
     */
    public static <O, K, V> O mapToObject(Map<K, V> map, TypeReference<O> typeReference) {
        return JSON.parseObject(JSON.toJSONString(map), typeReference);
    }

    /**
     * Map集合转对象
     *
     * @param map
     * @param clazz
     * @param <O>
     * @param <K>
     * @param <V>
     * @return
     */
    public static <O, K, V> O mapToObject(Map<K, V> map, Class<O> clazz) {
        return JSON.parseObject(JSON.toJSONString(map), clazz);
    }

    /**
     * List集合转Map集合
     *
     * @param src
     * @param getter
     * @param <K>
     * @param <V>
     * @return
     */
    public static <K, V> Map<K, V> list2Map(List<V> src, KeyGetter<K, V> getter) {
        HashMap<K, V> map = new HashMap<>(INITIAL_CAPACITY);
        list2Map(src, getter, map);
        return map;
    }

    public static <K, V> void list2Map(List<V> src, KeyGetter<K, V> getter, Map<K, V> dest) {
        if (isEmpty(src)) {
            return;
        }

        for (V value : src) {
            K key = getter.getKey(value);
            dest.put(key, value);
        }
    }

    private static <V> boolean isEmpty(Collection<V> src) {
        return src == null || src.isEmpty();
    }

    @FunctionalInterface
    public interface KeyGetter<K, V> {

        /**
         * 得到key
         *
         * @param value
         * @return
         */
        K getKey(V value);
    }
}
